#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#include "Token/Token.h"
#include "Scanner.h"

bool hadError = false;
string source;

void runFile(const char* path);
void runPrompt();
void run();
void error(int line, int column, const string& message);
void report(int line, int column, const string& where, const string& message);
string getLine(int line);

int main(int argc, char* argv[]) {
    if (argc>2) {
        cerr<<"Usage: loxpp [script]";
        return 64;
    } else if (argc==2) {
        runFile(argv[1]);
    } else {
        runPrompt();
    }
    return 0;
}

void runFile(const char* path) {
    freopen(path, "r", stdin);
    string tmp;
    while (getline(cin, tmp), cin) {
        source+=(tmp+'\n');
    }
    run();

    if (hadError) exit(65);
}

void runPrompt() {
    printf(">>>");
    while(getline(cin, source), cin) {
        run();
        hadError=false;
        printf(">>>");
    }
}

void run() {
    Scanner scanner(source);
    vector<Token> tokens = scanner.scanTokens();

    //For now, simply output the tokens
    for (Token token: tokens) {
        cout<<token.toString()<<endl;
    }
}

void error(int line, int column, const string& message) {
    report(line, column, "", message);
}

void report(int line, int column, const string& where, const string& message) {
    cout<<"[Error]: "<<where<<message<<endl;

    char buffer[128];
    sprintf(buffer, "[%d, %d] | ", line, column);
    int prefixLength = static_cast<int>(strlen(buffer))-1;

    printf("[%d, %d] | ", line, column); cout<<getLine(line)<<endl;

    for (int i=1; i<prefixLength+column; i++)
        putchar(' ');
    printf("^-- Here\n");

    hadError=true;
}

string getLine(int line) {
    int cnt = 0;
    string::const_iterator lst=source.cbegin();
    for (auto it=source.cbegin(); it!=source.cend(); it++) {
        //cout<<(*it)<<" "<<(*lst)<<" "<<cnt<<'\n';
        if (cnt<line) {
            if ((*it)=='\n') {
                cnt++;
                if (cnt==line) {
                    return source.substr(lst-source.cbegin(), it-lst);
                }
            }
        }
    }
    return "Error in getLine().";
}